#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>

// Should be same with the one in lihttpd.conf and index.html.
#define DEFAULT_PORT 8081
// Should be same with the one in lihttpd.conf.
#define DEFAULT_IP "127.0.0.1"

int main(int argc, char **argv)
{
    int server_socket = -1;
    int client_socket = -1;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    char received_buffer[1024]; // Buffer for received.
    int received_len = -1;
    int sended_len = -1;
    int res = -1;
    socklen_t addr_len = sizeof(struct sockaddr);
    int index;

    // Create a socket.
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0)
    {
        printf("Create socket failed: %s\n", strerror(errno));
        return -1;
    }

    // Bind the created socket on special IP and port.
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(DEFAULT_PORT);
    server_addr.sin_addr.s_addr = inet_addr(DEFAULT_IP);
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        printf("Bind server failed: %s\n", strerror(errno));
        return -2;
    }
    printf("Socket[%d] has bond on port[%d] for IP address[%s]!\n",
           server_socket, DEFAULT_PORT, DEFAULT_IP);

    // Listen on the created socket.
    listen(server_socket, 10);

    while (1)
    {
        printf("Waiting and accept new client connect...\n");

        client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len);
        if (client_socket < 0)
        {
            printf("Accept client socket failed: %s\n", strerror(errno));
            return -3;
        }

        printf("Accept new client[%d] socket[%s:%d]\n", client_socket,
               inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        while (1)
        {
            memset(received_buffer, 0, sizeof(received_buffer));

            received_len = read(client_socket, received_buffer, sizeof(received_buffer));
            if (received_len < 0)
            {
                printf("Read data from client [%d] failed: %s\n", client_socket, strerror(errno));
                close(client_socket);
                break;
            }
            else if (0 == received_len)
            {
                printf("Client [%d] disconnected!\n", client_socket);
                close(client_socket);
                break;
            }
            else
            {
                printf("Read %d bytes from client[%d] and the data is : %s\n",
                       received_len, client_socket, received_buffer);
                // Send back the received buffer to client.
                sended_len = write(client_socket, received_buffer, received_len);
                if (sended_len < 0)
                {
                    printf("wWite data back to client[%d] failed: %s \n", client_socket,
                           strerror(errno));
                    close(client_socket);
                    break;
                }
            }
        }
        sleep(1);
    }

    if (client_socket)
    {
        close(client_socket);
    }
    close(server_socket);

    return 1;
}